package com.iam.core.base;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.base.CaseFormat;
import com.iam.core.entities.BasePaginationEntity;
import com.iam.core.entities.IFilter;
import com.iam.core.entities.IParams;
import com.iam.core.entities.Result;
import com.iam.core.enums.EntityStatus;
import com.iam.core.exceptions.CustomException;
import com.iam.core.utils.ResultUtil;
import org.springframework.http.HttpStatus;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static com.iam.core.service.AbstractBaseCommonService.PARAM_ORDER_ASC_KEY;
import static com.iam.core.service.AbstractBaseCommonService.PARAM_ORDER_DESC_KEY;

/**
 * <控制器基类>
 *
 * @author baily
 * @date 2019/7/11
 * @since 1.0
 **/
public abstract class BaseCommonController<M extends BasePaginationEntity> {

    public static final String ROLE_ADMIN = "admin";

    public static final String COMPANYID = "companyId";

    /**
     * 获取服务
     *
     * @return
     */
    abstract public BaseCommonService<M> getiService();

    /**
     * 获取模块名称
     *
     * @return
     */
    abstract public String getMouduleName();

    @PostMapping("/index")
    public Result index(@RequestBody IParams params) {
        if (params.hasFilter(COMPANYID) && StpUtil.hasRole(ROLE_ADMIN)) {
            List<IFilter> filters = params.getFilters();
            ArrayList<IFilter> iFilters = new ArrayList<>();
            for (IFilter filter : filters) {
                if (!filter.getFieldName().equals(COMPANYID)) {
                    iFilters.add(filter);
                }
            }
            params.setFilters(iFilters);
        }
        Page<M> page = new Page<>(params.getPage(), params.getPageSzie());
        Page<M> mPage = getiService().page(page, buildWrapper(params));
        return ResultUtil.success(mPage);
    }

    /**
     * 获取详情
     *
     * @param id
     * @return
     */
    @GetMapping("/get")
    public Result details(@RequestParam("id") Serializable id) {
        Object obj = getiService().getById(id);
        if (ObjectUtils.isEmpty(obj)) {
            return ResultUtil.notFound();
        }
        return ResultUtil.success(obj);
    }

    /**
     * 保存
     *
     * @param entity
     * @return
     */
    @PostMapping
    public Result save(@RequestBody @Validated M entity) {
        if (exist(entity)) {
            return ResultUtil.error(500, getMouduleName() + "已存在");
        }
        // 设置边角料属性
        entity.setCreator(StpUtil.getLoginIdAsInt());
        entity.setUpdator(StpUtil.getLoginIdAsInt());
        entity.setUpdateAt(new Date());
        entity.setCreateAt(new Date());
        entity.setStatus(EntityStatus.NORMAL);

        boolean insert = getiService().save(entity);
        if (insert) {
            return ResultUtil.success("新增" + getMouduleName() + "成功");
        }
        return ResultUtil.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), "新增" + getMouduleName() + "失败");
    }

    /**
     * 更新
     *
     * @param entity
     * @return
     */
    @PostMapping("/update")
    public Result update(@RequestBody M entity) {
        entity.setUpdateAt(new Date());
        entity.setUpdator(StpUtil.getLoginIdAsInt());
        if (getiService().updateById(entity)) {
            return ResultUtil.success("修改" + getMouduleName() + "成功");
        }
        return ResultUtil.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), "修改" + getMouduleName() + "失败");
    }

    /**
     * 删除
     *
     * @param id 主键
     * @return
     */
    @DeleteMapping("/{id}")
    public Result delete(@PathVariable Serializable id) {
        if (deleteAble(id) && getiService().removeById(id)) {
            return ResultUtil.success("删除" + getMouduleName() + "成功");
        }
        return ResultUtil.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), "删除" + getMouduleName() + "失败");
    }

    @PostMapping("/all")
    public Result all() {
        return ResultUtil.success(getiService().list());
    }

    public boolean deleteAble(Serializable id) {
        Object detail = getiService().getById(id);
        if (ObjectUtils.isEmpty(detail)) {
            throw new CustomException("未发现目标对象");
        }
        return true;
    }

    public QueryWrapper<M> buildWrapper(IParams params) {
        QueryWrapper<M> wrapper = new QueryWrapper<>();
        for (IFilter filter : params.getFilters()) {
            if (!StringUtils.isEmpty(filter.getFieldName())) {
                if (!StringUtils.isEmpty(filter.getCompare())) {
                    String fieldName = filter.getFieldName();
                    fieldName = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, fieldName);
                    switch (filter.getCompare()) {
                        case ">":
                            wrapper.gt(fieldName, filter.getFieldValue());
                            break;
                        case "<":
                            wrapper.lt(fieldName, filter.getFieldValue());
                            break;
                        case ">=":
                            wrapper.ge(fieldName, filter.getFieldValue());
                            break;
                        case "<=":
                            wrapper.le(fieldName, filter.getFieldValue());
                            break;
                        case "!=":
                            wrapper.ne(fieldName, filter.getFieldValue());
                            break;
                        case "=":
                            if(!StringUtils.isEmpty(filter.getFieldValue())) {
                                wrapper.eq(fieldName, filter.getFieldValue());
                            }
                            break;
                        case "like":
                            if(!StringUtils.isEmpty(filter.getFieldValue())) {
                                wrapper.like(fieldName, filter.getFieldValue());
                            }
                            break;
                        case "likeLeft":
                            wrapper.likeLeft(fieldName, filter.getFieldValue());
                            break;
                        case "likeRight":
                            wrapper.likeRight(fieldName, filter.getFieldValue());
                            break;
                        case "bt":
                            Object fieldValue = filter.getFieldValue();
                            if (!ObjectUtils.isEmpty(fieldValue)) {
                                String sv = (String) fieldValue;
                                if (sv.contains(",")) {
                                    wrapper.between(fieldName, sv.split(",")[0], sv.split(",")[1]);
                                }
                            }
                            break;
                        case "nbt":
                            Object nBtValue = filter.getFieldValue();
                            if (!ObjectUtils.isEmpty(nBtValue)) {
                                String sv = (String) nBtValue;
                                if (sv.contains(",")) {
                                    wrapper.notBetween(fieldName, sv.split(",")[0], sv.split(",")[1]);
                                }
                            }
                            break;
                        case "in":
                            if (!ObjectUtils.isEmpty(filter.getFieldValue())) {
                                wrapper.in(fieldName, CollectionUtils.arrayToList(filter.getFieldValue().toString().split(",")));
                            }
                            break;
                        default:
                            break;
                    }
                }
            }
        }

        if (!ObjectUtils.isEmpty(params.getOrderBy())) {
            if (params.getOrderBy().endsWith(PARAM_ORDER_DESC_KEY)) {
                wrapper.orderByDesc(params.getOrderBy().replace("desc", ""));
            } else if (params.getOrderBy().endsWith(PARAM_ORDER_ASC_KEY)) {
                wrapper.orderByAsc(params.getOrderBy().replace(PARAM_ORDER_ASC_KEY, ""));
            }
        }
        return wrapper;
    }

    /**
     * 判断是否重复
     *
     * @param entity
     * @return
     */
    public boolean exist(M entity) {
        return false;
    }


    /**
     * 获取业务KEY
     * 各个子类需要重写
     *
     * @return
     */
    public String getBusinessKey() {
        return "当使用到业务KEY的时候你必须重写这个方法！！";
    }

}
